<?php
declare(strict_types=1);
namespace Haozing\FastCore;

use Hyperf\Support\Composer;
use Hyperf\Support\Filesystem\Filesystem;
use Psr\Container\ContainerExceptionInterface;
use Psr\Container\NotFoundExceptionInterface;

class Core
{
    private static string $mineName = 'fastcore';
    /**
     * @var string
     */
    private static string $version = '0.0.1';

    /**
     * @var array
     */
    private array $appPath = [];

    /**
     * @var array
     */
    private static array $moduleInfo = [];

    private static array $pluginInfo = [];

    public function __construct()
    {
        $this->setAppPath([
            BASE_PATH . '/app',
        ]);
        $this->scanModule();
    }

    /**
     * @param array $appPath
     */
    public function setAppPath(array $appPath): void
    {
        $this->appPath = $appPath;
    }
    public function getAppPath(): array
    {
        $paths = [];
        foreach ($this->appPath as $path) {
            $paths[] = $path . DIRECTORY_SEPARATOR;
        }
        return $paths;
    }
    /**
     * @throws ContainerExceptionInterface
     * @throws NotFoundExceptionInterface
     */
    public function scanModule(): void
    {
        $infos = [];
        foreach (self::getAppPath() as $path) {
            $modules = glob($path . '*');
            $fs = container()->get(Filesystem::class);
            foreach ($modules as $mod) if (is_dir($mod)) {
                // 读取模块配置
                if (file_exists($mod. DIRECTORY_SEPARATOR. 'plugin.php')) {
                    $modInfo = include $mod. DIRECTORY_SEPARATOR. 'plugin.php';
                    //$mod字符串从头去掉$this->appPath
                    $pathString = ltrim($mod,$path);
                    //将$pathString 转化为数组
                    $paths = explode(DIRECTORY_SEPARATOR, $pathString);
                    //制作namespace路径，分隔符为\\
                    $namespace = implode('\\',$paths);
                    //设置namespace
                    $modInfo['namespace'] =  'App\\' . $namespace;

                    $modInfo['name'] = strtolower($pathString);
                    //pluginPath
                    $modInfo['pluginPath'] = $mod;
                    //判断order是否存在，不存在则为0
                    if (!isset($modInfo['order'])) {
                        $modInfo['order'] = 0;
                    }
                    //获取name,为
                    $infos[$modInfo['name']] = $modInfo;
                }
            }
        }

        $sortId = array_column($infos, 'order');
        array_multisort($sortId, SORT_ASC, $infos);
        $this->setModuleInfo($infos);
    }

    /**
     * @param mixed $moduleInfo
     */
    public function setModuleInfo(mixed $moduleInfo): void
    {
        self::$moduleInfo = $moduleInfo;
    }

    /**
     * @param string|null $name
     * @return mixed
     */
    public function getModuleInfo(string $name = null): array
    {
        if (empty($name)) {
            return self::$moduleInfo;
        }
        return self::$moduleInfo[$name] ?? [];
    }
    /**
     * 获取plugin信息
     */
    public function getPluginInfo(string $pluginName = null): array
    {
        $pluginInfo = [];
        //判断pluginInfo是否存在，如果存在，直接返回
        if (!empty(self::$pluginInfo)) {
            $pluginInfo = self::$pluginInfo;
        }else{

            $extra = Composer::getLockContent()->toArray();
            //判断是否存在$extra['packages']
            if (isset($extra['packages'])) {
                //如果$extra['packages']是数组，遍历$extra['packages']，并寻找name是$pluginName的package
                foreach ($extra['packages'] as $package) {
                    //查询name字符串开头是否是'plugin/'开头
                    if (str_starts_with($package['name'], 'plugin'.DIRECTORY_SEPARATOR)) {
                        $info = [
                            'order' => 0,
                            'errorCode' => '100',
                            'hooks' => [],
                            'events' => [],
                        ];
                        //如果是，则将name截取掉'plugin/'
                        $name = substr($package['name'], 7);
                        $info['name'] =strtolower($name);
                        $provider = $package['extra']['hyperf']['config']?? '';
                        //判断provider是否存在，不存在则为''
                        if (empty($provider)) {
                            continue;
                        }
                        //去掉字符串最后的ConfigProvider
                        $info['namespace'] = substr($provider, 0, -15);
                        if (is_string($provider) && class_exists($provider) && method_exists($provider, '__invoke')) {
                            $providerConfig = (new $provider())();
                            //判断$providerConfig['path'];是否存在
                            if (!isset($providerConfig['path'])) {
                                continue;
                            }
                            //pluginPath
                            $info['pluginPath'] = $providerConfig['path'];
                            //判断order是否存在，不存在则为0
                            if (isset($providerConfig['plugin'])) {
                                $info['order'] = $providerConfig['plugin']['order']?? 0;
                                $info['errorCode'] = $providerConfig['plugin']['errorCode']?? '100';
                                $info['hooks'] = $providerConfig['plugin']['hooks']?? [];
                                $info['events'] = $providerConfig['plugin']['events']?? [];
                            }
                        }
                        $pluginInfo[$info['name']] = $info;
                    }
                }
                $sortId = array_column($pluginInfo, 'order');
                array_multisort($sortId, SORT_ASC, $pluginInfo);
                self::$pluginInfo = $pluginInfo;
            }
        }

        if (empty($pluginName)) {
            return $pluginInfo;
        }else {
            return $pluginInfo[$pluginName] ?? [];
        }
    }

    /**
     * @return string
     */
    public static function getVersion(): string
    {
        return self::$version;
    }
}